﻿using System;
using Csla;
using Csla.Serialization;
using BizControl.DalLinq;
using BizControl.Resources;
using BizControl.Library.BusinessObjects.Models;
using BizControl.Library.BusinessObjects.Marks;
using System.Linq;
using System.Collections.Specialized;

namespace BizControl.Library.BusinessObjects.People
{
  [Serializable()]
  public class PersonMarks : BusinessListBase<PersonMarks, PersonMarkLinkBO>
  {
    #region  Business Methods

    private PersonBO _person;
    
    public PersonMarkLinkBO this[Guid? personMarkIdFor]
    {
      get
      {
        if (personMarkIdFor == null || personMarkIdFor == Guid.Empty) return null;
        foreach (PersonMarkLinkBO personMark in this)
        {
          if (personMark.Mark.Id == personMarkIdFor)
            return personMark;
        }
        return null;
      }
    }

    public void AddMark(PersonMarkBO mark)
    {
      if (!(Contains(mark.MarkId)))
      {
        PersonMarkLinkBO personMark = PersonMarkLinkBO.NewPersonMarkLink(_person, mark);
        this.Add(personMark);
      }
      else
      {
        throw new InvalidOperationException(ExceptionsMessages.PersonAlreadyHasThisMark);
      }
    }

    public void Remove(Guid markId)
    {
      foreach (PersonMarkLinkBO personMark in this)
      {
        if (personMark.Mark.Id == markId)
        {
          Remove(personMark);
          break;
        }
      }
    }

    public bool Contains(Guid markId)
    {
      foreach (PersonMarkLinkBO personMark in this)
        if (personMark.Mark.Id == markId)
          return true;
      return false;
    }

    public bool ContainsDeleted(Guid markId)
    {
      foreach (PersonMarkLinkBO personMark in DeletedList)
        if (personMark.Mark.Id == markId)
          return true;
      return false;
    }

    #endregion

    #region  Factory Methods

    internal static PersonMarks NewPersonMarks(PersonBO person)
    {
      return DataPortal.CreateChild<PersonMarks>(person);
    }

    internal static PersonMarks GetPersonMarks(PersonMark[] data, PersonBO person)
    {
      return DataPortal.FetchChild<PersonMarks>(data, person);
    }

    private PersonMarks()
    {
      CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(PersonMarks_CollectionChanged);
    }

    void PersonMarks_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
      if (_person != null)
        _person.HasMarks = true;
    }

    #endregion

    #region  Data Access

    private void Child_Create(PersonBO person)
    {
      if (person == null) throw new ArgumentNullException(ExceptionsMessages.PersonNullReference);
      _person = person;
      base.Child_Create();
    }

    private void Child_Fetch(PersonMark[] data, PersonBO person)
    {
      if (person == null) throw new ArgumentNullException(ExceptionsMessages.PersonNullReference);
      _person = person;
      if (data == null) return;
      this.RaiseListChangedEvents = false;
      foreach (var child in data)
        Add(PersonMarkLinkBO.GetPersonMarkLink(child, _person));
      this.RaiseListChangedEvents = true;
    }

    #endregion
  }
}